/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package managedbean.MrpMps;

import merlion.mrp.ppm.pojo.DoubleHolder;
import merlion.mrp.ppm.pojo.LongHolder;
import java.sql.Timestamp;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import javax.ejb.EJB;
import javax.faces.application.FacesMessage;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.ViewScoped;
import javax.faces.context.FacesContext;
import javax.faces.event.ActionEvent;
import merlion.common.util.Consts;
import merlion.mrp.ppm.entity.DailyMPS;
import merlion.mrp.ppm.entity.DailyPlannedProduction;
import merlion.mrp.ppm.entity.Product;
import merlion.mrp.ppm.pojo.ScheduleResultTemp;
import merlion.mrp.ppm.session.MPSPlanningSessionLocal;
import org.primefaces.context.RequestContext;

/**
 *
 * @author Zhang Ying
 */
@ManagedBean
@ViewScoped
public class DailyMpsEditManagerBean {
    // for detail page

    @EJB
    private MPSPlanningSessionLocal mspSession;
    private DailyMPS editDMPS;
    private ArrayList<Integer> counterForProduct;
    private ArrayList<Integer> counterForWeek;
    private ArrayList<ArrayList<Long>> dailyDemands;
    private ArrayList<ArrayList<LongHolder>> dailyDemandsInput;
    private ArrayList<ArrayList<Long>> dailyOTDemands;
    private ArrayList<ArrayList<LongHolder>> dailyOTDemandsInput;
    private ArrayList<Timestamp> times;
    private ArrayList<Long> monthlyDemands;
    private Integer totalWorkingDays;
    // for scheduling dialog
    private ScheduleResultTemp scheduleResult;
    private ScheduleResultTemp manScheduleResult;
    private ArrayList<ArrayList<ArrayList<DoubleHolder>>> scheduledNormalResults; // 5 * 4 * 2
    private ArrayList<ArrayList<ArrayList<DoubleHolder>>> scheduledOvertimeResults; // 5 * 4 *2
    private ArrayList<ArrayList<DoubleHolder>> normalScheduledCapacities; // 5 * 2
    private ArrayList<ArrayList<DoubleHolder>> overtimeScheduledCapacities; // 5 * 2
    private ArrayList<ArrayList<DoubleHolder>> normalScheduledUtilization; // 5 * 2
    private ArrayList<ArrayList<DoubleHolder>> overtimeScheduledUtilization; // 5 * 2

    /** Creates a new instance of DailyMpsEditManagerBean */
    public DailyMpsEditManagerBean() {
        counterForProduct = new ArrayList<Integer>();
        for (int i = 0; i < 4; i++) {
            counterForProduct.add(i);
        }
        counterForWeek = new ArrayList<Integer>();
        for (int i = 0; i < 5; i++) {
            counterForWeek.add(i);
        }
    }

    // edit 
    public DailyMPS getEditDMPS() {
        if (editDMPS == null) {
            DailyMPS dmps = (DailyMPS) FacesContext.getCurrentInstance().getExternalContext().getSessionMap().get(DailyMpsViewManagerBean.EDITED_DMPS);
            editDMPS = dmps;
        }
        return editDMPS;
    }

    public void setEditDMPS(DailyMPS editDMPS) {
        this.editDMPS = editDMPS;
    }

    public ArrayList<Integer> getCounterForProduct() {
        return counterForProduct;
    }

    public ArrayList<Integer> getCounterForWeek() {
        return counterForWeek;
    }

    // for detail page
    public String calculateDMPS() {
        //  add validations
        // 1. check 90%
        for (int j = 0; j < 5; j++) {
            Integer totalDaysPW = 16;
            double sumOfHrs = Long.valueOf(0);
            Integer totalDaysPWP = 8;
            double sumOfHrsP = Long.valueOf(0);
            for (int i = 0; i < 4; i++) {
                if (i == 0 || i == 1) {
                    sumOfHrs += 1.0 * dailyDemandsInput.get(i).get(j).getL() / Consts.CASES_PER_HOUR_CLASSIC;
                    sumOfHrsP += 1.0 * dailyOTDemandsInput.get(i).get(j).getL() / Consts.CASES_PER_HOUR_CLASSIC;
                } else {
                    sumOfHrs += 1.0 * dailyDemandsInput.get(i).get(j).getL() / Consts.CASES_PER_HOUR_PREMIUM;
                    sumOfHrsP += 1.0 * dailyOTDemandsInput.get(i).get(j).getL() / Consts.CASES_PER_HOUR_PREMIUM;
                }
            }
            System.out.println("utilization:" + 1.0 * sumOfHrs / totalDaysPW);
            if (totalDaysPW != 0 && 1.0 * sumOfHrs / totalDaysPW > 0.9) {
                FacesContext.getCurrentInstance().addMessage(null,
                        new FacesMessage(FacesMessage.SEVERITY_ERROR, "Unsuccessful",
                        "Please make sure the utilization for normal shift is less than 90%."));
                return null;
            }
            if (totalDaysPWP != 0 && 1.0 * sumOfHrsP / totalDaysPWP > 0.9) {
                FacesContext.getCurrentInstance().addMessage(null,
                        new FacesMessage(FacesMessage.SEVERITY_ERROR, "Unsuccessful",
                        "Please make sure the utilization for overtime shift is less than 90%."));
                return null;
            }
        }
        // 2. check whether 21 days
        Calendar c1 = Calendar.getInstance();
        Calendar c2 = Calendar.getInstance();
        c1 = mspSession.getFirstMondayOfMonth(editDMPS.getStartPeriodYear(), editDMPS.getStartPeriodMonth());
        c1.add(Calendar.WEEK_OF_YEAR, editDMPS.getStartPeriodDate() - 1);  //start date of the DMPS
        c1.set(c1.get(Calendar.YEAR), c1.get(Calendar.MONTH), c1.get(Calendar.DAY_OF_MONTH), 0, 0, 0);
        //for testing
//        c2.set(2011, 12, 24);
        long millis1 = c1.getTimeInMillis();
        long millis2 = c2.getTimeInMillis(); // current time

        long d = (millis1 - millis2) / (24 * 60 * 60 * 1000);

        if ((d <= 21 && (millis1 - millis2) > 0) || (millis1 - millis2 < 0 && d > -5)) {
            // check for raw material
            System.out.println("::::::::::::::::::::::testing");
            ArrayList<ArrayList<Long>> saveReg1 = new ArrayList<ArrayList<Long>>();
            ArrayList<ArrayList<Long>> saveReg2 = new ArrayList<ArrayList<Long>>();
            // set the holders' values to editDMPS
            for (int i = 0; i < 4; i++) {
                ArrayList<Long> temp1 = new ArrayList<Long>();
                ArrayList<Long> temp2 = new ArrayList<Long>();
                for (int j = 0; j < 5; j++) {
                    DailyPlannedProduction dpp = editDMPS.returnIndivDMPS(i).returnDailyPlannedProduction(j);
                    Long l1 = new Long(dpp.getDailyDemand());
                    Long l2 = new Long(dpp.getDailyOTDemand());
                    temp1.add(l1);
                    temp2.add(l2);
                    dpp.setDailyDemand(dailyDemandsInput.get(i).get(j).getL());
                    dpp.setDailyOTDemand(dailyOTDemandsInput.get(i).get(j).getL());
                }
                saveReg1.add(temp1);
                saveReg2.add(temp2);
            }
            if (!mspSession.checkRawMaterial(editDMPS)) {
                for (int i = 0; i < 4;i++) {
                    for (int j = 0; j < 5; j ++) {
                        DailyPlannedProduction dpp = editDMPS.returnIndivDMPS(i).returnDailyPlannedProduction(j);
                        dpp.setDailyDemand(saveReg1.get(i).get(j));
                        dpp.setDailyOTDemand(saveReg2.get(i).get(j));
                    }
                }
                FacesContext.getCurrentInstance().addMessage(null,
                        new FacesMessage(FacesMessage.SEVERITY_ERROR, "Unsuccessful",
                        "Sorry. You don't have enough material. Please edit your inputs"));
                return null;
            }
        }
        FacesContext.getCurrentInstance().addMessage(null,
                new FacesMessage(FacesMessage.SEVERITY_INFO, "Successful",
                "Calculation done."));
        // set the holders' values to editDMPS
//        for (int i = 0; i < 4; i++) {
//            for (int j = 0; j < 5; j++) {
//                DailyPlannedProduction dpp = editDMPS.returnIndivDMPS(i).returnDailyPlannedProduction(j);
//                dpp.setDailyDemand(dailyDemandsInput.get(i).get(j).getL());
//                dpp.setDailyOTDemand(dailyOTDemandsInput.get(i).get(j).getL());
//            }
//        }
        // debugging
//        for (int i = 0; i < 4; i++) {
//            for (int j = 0; j < 5; j++) {
//                DailyPlannedProduction dpp = editDMPS.returnIndivDMPS(i).returnDailyPlannedProduction(j);
//                System.out.println("dpp " + dpp.getDailyDemand() + " " + dpp.getDailyOTDemand());
//            }
//        }
        return null;
    }

    public void scheduleDMPS(ActionEvent event) {
        // call schedule function
        RequestContext requestContext = RequestContext.getCurrentInstance();
        requestContext.addCallbackParam("isValid", true);

        // 1. check 90%
        for (int j = 0; j < 5; j++) {
            Integer totalDaysPW = 16;
            double sumOfHrs = Long.valueOf(0);
            Integer totalDaysPWP = 8;
            double sumOfHrsP = Long.valueOf(0);
            for (int i = 0; i < 4; i++) {
                if (i == 0 || i == 1) {
                    sumOfHrs += 1.0 * dailyDemandsInput.get(i).get(j).getL() / Consts.CASES_PER_HOUR_CLASSIC;
                    sumOfHrsP += 1.0 * dailyOTDemandsInput.get(i).get(j).getL() / Consts.CASES_PER_HOUR_CLASSIC;
                } else {
                    sumOfHrs += 1.0 * dailyDemandsInput.get(i).get(j).getL() / Consts.CASES_PER_HOUR_PREMIUM;
                    sumOfHrsP += 1.0 * dailyOTDemandsInput.get(i).get(j).getL() / Consts.CASES_PER_HOUR_PREMIUM;
                }
            }
            if (totalDaysPW != 0 && 1.0 * sumOfHrs / totalDaysPW > 0.9) {
                FacesContext.getCurrentInstance().addMessage(null,
                        new FacesMessage(FacesMessage.SEVERITY_ERROR, "Unsuccessful",
                        "Please make sure the utilization for normal shift is less than 90% and then do the scheduling."));
                requestContext.addCallbackParam("isValid", false);
                return;
            }
            if (totalDaysPWP != 0 && 1.0 * sumOfHrsP / totalDaysPWP > 0.9) {
                FacesContext.getCurrentInstance().addMessage(null,
                        new FacesMessage(FacesMessage.SEVERITY_ERROR, "Unsuccessful",
                        "Please make sure the utilization for overtime shift is less than 90% and then do the scheduling."));
                requestContext.addCallbackParam("isValid", false);
                return;
            }
        }

        scheduleResult = mspSession.getScheduleResult(editDMPS);
        if (scheduleResult.isNeedHumanIntervention()) {
            FacesContext.getCurrentInstance().addMessage(null,
                    new FacesMessage(FacesMessage.SEVERITY_ERROR, "Unsuccessful",
                    "Sorry. Please make sure the capacity is less than 90%"));
            requestContext.addCallbackParam("isValid", false);
        }
    }

    public void checkScheduleCapacity(ActionEvent event) {
        // check one day equal one day
        for (int i = 0; i < 5; i++) {
            for (int j = 0; j < 4; j++) {
                for (int k = 0; k < 2; k++) {
                    if (scheduledNormalResults.get(i).get(j).get(k).getD() < 0
                            || scheduledOvertimeResults.get(i).get(j).get(k).getD() < 0) {
                        FacesContext.getCurrentInstance().addMessage(null,
                                new FacesMessage(FacesMessage.SEVERITY_ERROR, "Unsuccessful",
                                "Sorry. Your scheduling fields cannot be negative"));
                        return;
                    }
                }
                if (!checkEqualTodayDemand(j,
                        scheduledNormalResults.get(i).get(j).get(0).getD(),
                        scheduledNormalResults.get(i).get(j).get(1).getD(),
                        editDMPS.returnIndivDMPS(j).returnDailyPlannedProduction(i).getDailyDemand())) {
                    FacesContext.getCurrentInstance().addMessage(null,
                            new FacesMessage(FacesMessage.SEVERITY_ERROR, "Unsuccessful",
                            "Sorry. Your scheduling fields don't match your planned daily demands on day" + (i + 1) + " for product " + (j + 1)));
                    return;
                }
                if (!checkEqualTodayDemand(j,
                        scheduledOvertimeResults.get(i).get(j).get(0).getD(),
                        scheduledOvertimeResults.get(i).get(j).get(1).getD(),
                        editDMPS.returnIndivDMPS(j).returnDailyPlannedProduction(i).getDailyOTDemand())) {
                    FacesContext.getCurrentInstance().addMessage(null,
                            new FacesMessage(FacesMessage.SEVERITY_ERROR, "Unsuccessful",
                            "Sorry. Your scheduling fields don't match your planned daily overtime demands on day" + (i + 1) + " for product " + (j + 1)));
                    return;
                }
            }
        }
        // calculate capacity and utilization
        for (int i = 0; i < 5; i++) {
            ArrayList<Double> nline1 = new ArrayList<Double>();
            ArrayList<Double> nline2 = new ArrayList<Double>();
            ArrayList<Double> otline1 = new ArrayList<Double>();
            ArrayList<Double> otline2 = new ArrayList<Double>();
            for (int j = 0; j < 4; j++) {
                nline1.add(scheduledNormalResults.get(i).get(j).get(0).getD());
                nline2.add(scheduledNormalResults.get(i).get(j).get(1).getD());
                otline1.add(scheduledOvertimeResults.get(i).get(j).get(0).getD());
                otline2.add(scheduledOvertimeResults.get(i).get(j).get(1).getD());
            }
            normalScheduledCapacities.get(i).get(0).setD(mspSession.returnCapacity(true, nline1));
            normalScheduledUtilization.get(i).get(0).setD(mspSession.returnUtilization(true, nline1));
            overtimeScheduledCapacities.get(i).get(0).setD(mspSession.returnCapacity(false, otline1));
            overtimeScheduledUtilization.get(i).get(0).setD(mspSession.returnUtilization(false, otline1));
            normalScheduledCapacities.get(i).get(1).setD(mspSession.returnCapacity(true, nline2));
            normalScheduledUtilization.get(i).get(1).setD(mspSession.returnUtilization(true, nline2));
            overtimeScheduledCapacities.get(i).get(1).setD(mspSession.returnCapacity(false, otline2));
            overtimeScheduledUtilization.get(i).get(1).setD(mspSession.returnUtilization(false, otline2));
        }
        // check util less than 90%
        for (int i = 0; i < 5; i++) {
            for (int j = 0; j < 2; j++) {
                if (normalScheduledUtilization.get(i).get(j).getD() > 0.9
                        || overtimeScheduledUtilization.get(i).get(j).getD() > 0.9) {
                    FacesContext.getCurrentInstance().addMessage(null,
                            new FacesMessage(FacesMessage.SEVERITY_ERROR, "Unsuccessful",
                            "Please make sure the utilization for shift line is less than 90%."));
                    return;
                }
            }
        }
    }

    private boolean checkEqualTodayDemand(int productId, double demand1, double demand2, double totalDemand) {
        System.out.println("productid :" + productId + " demand1 :" + demand1 + " demand2 " + demand2 + " toal dem :" + totalDemand);
        if (productId == 0 || productId == 1) {
            if (Math.abs((demand1 + demand2) * Consts.CASES_PER_HOUR_CLASSIC - totalDemand) < 0.1) {
                return true;
            } else {
                return false;
            }
        } else {
            if (Math.abs((demand1 + demand2) * Consts.CASES_PER_HOUR_PREMIUM - totalDemand) < 0.1) {
                return true;
            } else {
                return false;
            }
        }
    }

    public void scheduleDMPS2(ActionEvent event) {
        RequestContext requestContext = RequestContext.getCurrentInstance();
        requestContext.addCallbackParam("isValid", true);

        // 1. check 90%
        for (int j = 0; j < 5; j++) {
            Integer totalDaysPW = 16;
            double sumOfHrs = Long.valueOf(0);
            Integer totalDaysPWP = 8;
            double sumOfHrsP = Long.valueOf(0);
            for (int i = 0; i < 4; i++) {
                if (i == 0 || i == 1) {
                    sumOfHrs += 1.0 * dailyDemandsInput.get(i).get(j).getL() / Consts.CASES_PER_HOUR_CLASSIC;
                    sumOfHrsP += 1.0 * dailyOTDemandsInput.get(i).get(j).getL() / Consts.CASES_PER_HOUR_CLASSIC;
                } else {
                    sumOfHrs += 1.0 * dailyDemandsInput.get(i).get(j).getL() / Consts.CASES_PER_HOUR_PREMIUM;
                    sumOfHrsP += 1.0 * dailyOTDemandsInput.get(i).get(j).getL() / Consts.CASES_PER_HOUR_PREMIUM;
                }
            }
            if (totalDaysPW != 0 && 1.0 * sumOfHrs / totalDaysPW > 0.9) {
                FacesContext.getCurrentInstance().addMessage(null,
                        new FacesMessage(FacesMessage.SEVERITY_ERROR, "Unsuccessful",
                        "Please make sure the utilization for normal shift is less than 90% and then do the scheduling."));
                requestContext.addCallbackParam("isValid", false);
                return;
            }
            if (totalDaysPWP != 0 && 1.0 * sumOfHrsP / totalDaysPWP > 0.9) {
                FacesContext.getCurrentInstance().addMessage(null,
                        new FacesMessage(FacesMessage.SEVERITY_ERROR, "Unsuccessful",
                        "Please make sure the utilization for overtime shift is less than 90% and then do the scheduling."));
                requestContext.addCallbackParam("isValid", false);
                return;
            }
        }

        // for manual scheduling
        manScheduleResult = mspSession.getScheduleResult(editDMPS);

        // substiute the fields
        scheduledNormalResults = new ArrayList<ArrayList<ArrayList<DoubleHolder>>>();
        scheduledOvertimeResults = new ArrayList<ArrayList<ArrayList<DoubleHolder>>>();
        normalScheduledCapacities = new ArrayList<ArrayList<DoubleHolder>>();
        overtimeScheduledCapacities = new ArrayList<ArrayList<DoubleHolder>>();
        normalScheduledUtilization = new ArrayList<ArrayList<DoubleHolder>>();
        overtimeScheduledUtilization = new ArrayList<ArrayList<DoubleHolder>>();
        for (int i = 0; i < 5; i++) {
            ArrayList<ArrayList<DoubleHolder>> normal = new ArrayList<ArrayList<DoubleHolder>>();
            ArrayList<ArrayList<DoubleHolder>> ot = new ArrayList<ArrayList<DoubleHolder>>();
            for (int j = 0; j < 4; j++) {
                ArrayList<DoubleHolder> n = new ArrayList<DoubleHolder>();
                ArrayList<DoubleHolder> o = new ArrayList<DoubleHolder>();
                for (int k = 0; k < 2; k++) {
                    n.add(new DoubleHolder(manScheduleResult.getScheduledNormalResults().get(i).get(j).get(k)));
                    o.add(new DoubleHolder(manScheduleResult.getScheduledOvertimeResults().get(i).get(j).get(k)));
                }
                normal.add(n);
                ot.add(o);
            }
            scheduledNormalResults.add(normal);
            scheduledOvertimeResults.add(ot);
        }
        for (int i = 0; i < 5; i++) {
            ArrayList<DoubleHolder> nsc = new ArrayList<DoubleHolder>();
            ArrayList<DoubleHolder> osc = new ArrayList<DoubleHolder>();
            ArrayList<DoubleHolder> nsu = new ArrayList<DoubleHolder>();
            ArrayList<DoubleHolder> osu = new ArrayList<DoubleHolder>();
            for (int j = 0; j < 2; j++) {
                nsc.add(new DoubleHolder(manScheduleResult.getNormalScheduledCapacities().get(i).get(j)));
                osc.add(new DoubleHolder(manScheduleResult.getOvertimeScheduledCapacities().get(i).get(j)));
                nsu.add(new DoubleHolder(manScheduleResult.getNormalScheduledUtilization().get(i).get(j)));
                osu.add(new DoubleHolder(manScheduleResult.getOvertimeScheduledUtilization().get(i).get(j)));
            }
            normalScheduledCapacities.add(nsc);
            overtimeScheduledCapacities.add(osc);
            normalScheduledUtilization.add(nsu);
            overtimeScheduledUtilization.add(osu);
        }

        if (manScheduleResult.isNeedHumanIntervention()) {
            FacesContext.getCurrentInstance().addMessage(null,
                    new FacesMessage(FacesMessage.SEVERITY_ERROR, "Unsuccessful",
                    "Sorry. Please make sure the capacity is less than 90%"));
            requestContext.addCallbackParam("isValid", false);
        }
    }

    public ArrayList<ArrayList<ArrayList<DoubleHolder>>> getScheduledNormalResults() {
        return scheduledNormalResults;
    }

    public ArrayList<ArrayList<DoubleHolder>> getNormalScheduledCapacities() {
        return normalScheduledCapacities;
    }

    public void setNormalScheduledCapacities(ArrayList<ArrayList<DoubleHolder>> normalScheduledCapacities) {
        this.normalScheduledCapacities = normalScheduledCapacities;
    }

    public ArrayList<ArrayList<DoubleHolder>> getNormalScheduledUtilization() {
        return normalScheduledUtilization;
    }

    public void setNormalScheduledUtilization(ArrayList<ArrayList<DoubleHolder>> normalScheduledUtilization) {
        this.normalScheduledUtilization = normalScheduledUtilization;
    }

    public ArrayList<ArrayList<DoubleHolder>> getOvertimeScheduledCapacities() {
        return overtimeScheduledCapacities;
    }

    public void setOvertimeScheduledCapacities(ArrayList<ArrayList<DoubleHolder>> overtimeScheduledCapacities) {
        this.overtimeScheduledCapacities = overtimeScheduledCapacities;
    }

    public ArrayList<ArrayList<DoubleHolder>> getOvertimeScheduledUtilization() {
        return overtimeScheduledUtilization;
    }

    public void setOvertimeScheduledUtilization(ArrayList<ArrayList<DoubleHolder>> overtimeScheduledUtilization) {
        this.overtimeScheduledUtilization = overtimeScheduledUtilization;
    }

    public ArrayList<ArrayList<ArrayList<DoubleHolder>>> getScheduledOvertimeResults() {
        return scheduledOvertimeResults;
    }

    public void setScheduledOvertimeResults(ArrayList<ArrayList<ArrayList<DoubleHolder>>> scheduledOvertimeResults) {
        this.scheduledOvertimeResults = scheduledOvertimeResults;
    }

    public ScheduleResultTemp getScheduleResult() {
        return scheduleResult;
    }

    public ScheduleResultTemp getManScheduleResult() {
        return manScheduleResult;
    }

    public String confirmDMPS() {
        //debugging
//        for (int i = 0; i < 4; i++) {
//            for (int j = 0; j < 5; j++) {
//                DailyPlannedProduction dpp = editDMPS.returnIndivDMPS(i).returnDailyPlannedProduction(j);
//                System.out.println("dpp " + dpp.getDailyDemand() + " " + dpp.getDailyOTDemand());
//            }
//        }
        // persist
        if (mspSession.updateDailyMPS2(editDMPS, dailyDemands, dailyOTDemands)) {
            FacesContext.getCurrentInstance().getExternalContext().getSessionMap().remove(DailyMpsViewManagerBean.EDITED_DMPS);
            return getRedirectPath(Consts.EDIT_DAILY_MPS_PATH + "Confirm");
        } else {
            FacesContext.getCurrentInstance().addMessage(null,
                    new FacesMessage(FacesMessage.SEVERITY_ERROR, "Unsuccessful",
                    "not able to persist into the database"));
            return null;
        }
    }

    public String resetDMPS() {
        dailyDemandsInput = new ArrayList<ArrayList<LongHolder>>();
        dailyOTDemandsInput = new ArrayList<ArrayList<LongHolder>>();
        for (int i = 0; i < 4; i++) {
            ArrayList<LongHolder> ddi = new ArrayList<LongHolder>();
            ArrayList<LongHolder> dotdi = new ArrayList<LongHolder>();
            for (int j = 0; j < 5; j++) {
                DailyPlannedProduction dpp = editDMPS.returnIndivDMPS(i).returnDailyPlannedProduction(j);
                dpp.setDailyDemand(dailyDemands.get(i).get(j));
                dpp.setDailyOTDemand(dailyOTDemands.get(i).get(j));

                LongHolder temp1 = new LongHolder();
                temp1.setL(dailyDemands.get(i).get(j));
                LongHolder temp2 = new LongHolder();
                temp2.setL(dailyOTDemands.get(i).get(j));
                ddi.add(temp1);
                dotdi.add(temp2);
            }
            dailyDemandsInput.add(ddi);
            dailyOTDemandsInput.add(dotdi);
        }
        FacesContext.getCurrentInstance().addMessage(null,
                new FacesMessage(FacesMessage.SEVERITY_INFO, "Successful",
                "reset the values"));
        return null;
    }

    public ArrayList<ArrayList<LongHolder>> getDailyDemandsInput() {
        fillInputs();
        return dailyDemandsInput;
    }

    public void setDailyDemandsInput(ArrayList<ArrayList<LongHolder>> dailyDemandsInput) {
        this.dailyDemandsInput = dailyDemandsInput;
    }

    public ArrayList<ArrayList<LongHolder>> getDailyOTDemandsInput() {
        fillInputs();
        return dailyOTDemandsInput;
    }

    private void fillInputs() {
        if (dailyDemandsInput == null || dailyDemandsInput.isEmpty()) {
            dailyDemandsInput = new ArrayList<ArrayList<LongHolder>>();
            dailyOTDemandsInput = new ArrayList<ArrayList<LongHolder>>();
            for (int i = 0; i < 4; i++) {
                ArrayList<LongHolder> ddi = new ArrayList<LongHolder>();
                ArrayList<LongHolder> dotdi = new ArrayList<LongHolder>();
                for (int j = 0; j < 5; j++) {
                    DailyPlannedProduction dpp = editDMPS.returnIndivDMPS(i).returnDailyPlannedProduction(j);
                    dpp.setDailyDemand(getDailyDemands().get(i).get(j));
                    dpp.setDailyOTDemand(getDailyOTDemands().get(i).get(j));
                    dpp.setProductionDay(times.get(j));
                    Product p = mspSession.getProduct(i);
                    dpp.setProduct(p);

                    LongHolder temp1 = new LongHolder();
                    temp1.setL(dailyDemands.get(i).get(j));
                    LongHolder temp2 = new LongHolder();
                    temp2.setL(dailyOTDemands.get(i).get(j));
                    ddi.add(temp1);
                    dotdi.add(temp2);
                }
                dailyDemandsInput.add(ddi);
                dailyOTDemandsInput.add(dotdi);
            }
        }
    }

    public void setDailyOTDemandsInput(ArrayList<ArrayList<LongHolder>> dailyOTDemandsInput) {
        this.dailyOTDemandsInput = dailyOTDemandsInput;
    }

    public Integer returnNormalShift() {
        return Consts.NORMAL_SHIFT_PER_DAY;
    }

    public Integer returnOvertimeShift() {
        return Consts.OVERTIME_EXTRA_SHIFT_PER_DAY;
    }

    public Double returnDailyDemandInHours(Long dailyDemand, int productCounter) {
        if (productCounter == 0) {
            return (1.0 * dailyDemand / Consts.CASES_PER_HOUR_CLASSIC);
        } else if (productCounter == 1) {
            return (1.0 * dailyDemand / Consts.CASES_PER_HOUR_CLASSIC);
        } else if (productCounter == 2) {
            return (1.0 * dailyDemand / Consts.CASES_PER_HOUR_PREMIUM);
        } else if (productCounter == 3) {
            return (1.0 * dailyDemand / Consts.CASES_PER_HOUR_PREMIUM);
        } else {
            return 0.0;
        }
    }

    public Double returnUtilizationNormalShift(Integer weekCount) {
        Integer totalDaysPW = 16;
        double sumOfHrs = Long.valueOf(0);
        for (int i = 0; i < 4; i++) {
            if (i == 0 || i == 1) {
                sumOfHrs += 1.0 * dailyDemandsInput.get(i).get(weekCount).getL() / Consts.CASES_PER_HOUR_CLASSIC;
            } else {
                sumOfHrs += 1.0 * dailyDemandsInput.get(i).get(weekCount).getL() / Consts.CASES_PER_HOUR_PREMIUM;
            }
        }
        if (totalDaysPW == 0) {
            return null;
        }
        return 1.0 * sumOfHrs / totalDaysPW;
    }

    public Double returnUtilizationOvertimeShift(Integer weekCount) {
        Integer totalDaysPW = 8;
        double sumOfHrs = Long.valueOf(0);
        for (int i = 0; i < 4; i++) {
            if (i == 0 || i == 1) {
                sumOfHrs += 1.0 * dailyOTDemandsInput.get(i).get(weekCount).getL() / Consts.CASES_PER_HOUR_CLASSIC;
            } else {
                sumOfHrs += 1.0 * dailyOTDemandsInput.get(i).get(weekCount).getL() / Consts.CASES_PER_HOUR_PREMIUM;
            }
        }
        if (totalDaysPW == 0) {
            return null;
        }
        return 1.0 * sumOfHrs / totalDaysPW;
    }

    public ArrayList<ArrayList<Long>> getDailyDemands() {
        if (dailyDemands == null) {
            dailyDemands = new ArrayList<ArrayList<Long>>();
            for (int i = 0; i < 4; i++) {
                ArrayList<Long> temp = new ArrayList<Long>();
                for (int j = 0; j < 5; j++) {
                    temp.add(getEditDMPS().returnIndivDMPS(i).returnDailyPlannedProduction(j).getDailyDemand());
                }
                dailyDemands.add(temp);
            }
        }
        return dailyDemands;
    }

    public void setDailyDemands(ArrayList<ArrayList<Long>> dailyDemands) {
        this.dailyDemands = dailyDemands;
    }

    public ArrayList<Timestamp> getTimes() {
        if (times == null) {
            times = mspSession.getDatesforWeek(getEditDMPS().getStartPeriodYear(), editDMPS.getStartPeriodMonth(), editDMPS.getStartPeriodDate());
        }
        return times;
    }

    public void setTimes(ArrayList<Timestamp> times) {
        this.times = times;
    }

    public ArrayList<Long> getMonthlyDemands() {
        if (monthlyDemands == null) {
            monthlyDemands = mspSession.getMonthlyDemand(getEditDMPS().getStartPeriodMonth(), editDMPS.getStartPeriodYear());
        }
        return monthlyDemands;
    }

    public void setMonthlyDemands(ArrayList<Long> monthlyDemands) {
        this.monthlyDemands = monthlyDemands;
    }

    public Integer getTotalWorkingDays() {
        if (totalWorkingDays == null) {
            totalWorkingDays = mspSession.getTotalWorkingDaysForMonth(getEditDMPS().getStartPeriodMonth(), editDMPS.getStartPeriodYear());
        }
        return totalWorkingDays;
    }

    public void setTotalWorkingDays(Integer totalWorkingDays) {
        this.totalWorkingDays = totalWorkingDays;
    }

    public ArrayList<ArrayList<Long>> getDailyOTDemands() {
        if (dailyOTDemands == null) {
            dailyOTDemands = new ArrayList<ArrayList<Long>>();
            for (int i = 0; i < 4; i++) {
                ArrayList<Long> temp = new ArrayList<Long>();
                for (int j = 0; j < 5; j++) {
                    temp.add(getEditDMPS().returnIndivDMPS(i).returnDailyPlannedProduction(j).getDailyOTDemand());
                }
                dailyOTDemands.add(temp);
            }
        }
        return dailyOTDemands;
    }

    public void setDailyOTDemands(ArrayList<ArrayList<Long>> dailyOTDemands) {
        this.dailyOTDemands = dailyOTDemands;
    }

    // for rendering
    public boolean renderEdit(Integer dayId) {
        boolean render = false;

        Timestamp pointedTime = times.get(dayId);
        int pointedYear = Integer.valueOf(Consts.sdfYear.format(pointedTime));
        int pointedMonth = Integer.valueOf(Consts.sdfMonth.format(pointedTime));
        int pointedDay = Integer.valueOf(Consts.sdfDay.format(pointedTime));

        Calendar c1 = Calendar.getInstance();
        c1.set(c1.get(Calendar.YEAR), c1.get(Calendar.MONTH), c1.get(Calendar.DAY_OF_MONTH), 0, 0, 0);
        Calendar c2 = Calendar.getInstance();

        //  for testing
        //c2.set(2011, 11, 24);
        c1.set(pointedYear, pointedMonth - 1, pointedDay, 0, 0, 0); // pointed planned time

        long millis1 = c1.getTimeInMillis();
        long millis2 = c2.getTimeInMillis(); // current time

        double d = (millis1 - millis2) / (24.0 * 60 * 60 * 1000);

        if (d >= 0 && millis1 > millis2) {
            render = true;
        }
//        System.out.println("pointed year: "+c1.get(Calendar.YEAR) + " month: "
//                + c1.get(Calendar.MONTH)+ " " +c1.get(Calendar.DAY_OF_MONTH)+" difference " + d
//                + " 1-2:" + (millis1 - millis2)
//                + " int: minus: " + (millis1 - millis2)/24*60*60*1000);
        return render;
    }

    // general
    private Long roundToLong(Double d) {
        return Math.round(d);
    }

    private String getRedirectPath(String path) {
        return path + "?faces-redirect=true";
    }

    public String returnProductAlpha(Integer i) {
        if (i.intValue() == 0) {
            //return Consts.ProductType.BAR_A.getText();
            return "A";
        } else if (i.intValue() == 1) {
            //return Consts.ProductType.BAR_B.getText();
            return "B";
        } else if (i.intValue() == 2) {
            //return Consts.ProductType.BAR_C.getText();
            return "C";
        } else if (i.intValue() == 3) {
            //return Consts.ProductType.BAR_D.getText();
            return "D";
        } else {
            return "";
        }
    }

    public String returnProductName(Integer i) {
        if (i.intValue() == 0) {
            return Consts.ProductType.BAR_A.getText();
        } else if (i.intValue() == 1) {
            return Consts.ProductType.BAR_B.getText();
        } else if (i.intValue() == 2) {
            return Consts.ProductType.BAR_C.getText();
        } else if (i.intValue() == 3) {
            return Consts.ProductType.BAR_D.getText();
        } else {
            return "";
        }
    }

    public String returnFormattedDay(Timestamp t) {
        if (t == null) {
            return "";
        }
        SimpleDateFormat sdf = new SimpleDateFormat("dd/MM");
        return sdf.format(t);
    }
}
